<?php
//
//	file: installer/install.php
//	begin: 19/01/2008
//	$Author: christopher $
//	$Revision: 29 $
//	$Date: 2008-07-19 15:59:35 +0000 (Sat, 19 Jul 2008) $
//	license: http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
//
//	simple framework for installing multiple db changes at once

define('IN_PHPBB', true);
define('IN_INSTALL', true);

$phpbb_root_path = './../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
$requester = 'installer/install';

include($phpbb_root_path . 'common.'.$phpEx);
include($config->url('includes/class_install'));
include($config->url('includes/class_cp'));

// constants
define('ROWS_A_TURN', 500);

// vars
$parts = array();
$part_script = array();
$cur_lang = false;

// steps
$steps = array(
	'IN_welcome',
	'IN_prev_vers',
	'IN_db',
	'IN_upgrade',
	'IN_init_data',
	'IN_patch',
	'IN_end',
);

// parms (not set is : type => TYPE_INT, default => 0)
$parms_def = array(
	'step' => array('list' => &$steps),
	'errcfg' => '',
	'inload' => array('type' => TYPE_INT, 'default' => 0),
);

// functions
function lang_include($lang_file)
{
	global $config, $lang, $cur_lang, $phpbb_root_path, $phpEx;

	if (!$cur_lang)
	{
		$cur_lang = guess_lang();
	}
	$lang_file = $phpbb_root_path . 'language/lang_%s/' . $lang_file . '.' . $phpEx;
	$file = sprintf($lang_file, $cur_lang);
	if ( @file_exists(@phpbb_realpath($file)) )
	{
		include($file);
	}
	else
	{
		$file = sprintf($lang_file, 'english');
		if ( @file_exists(@phpbb_realpath($file)) )
		{
			include($file);
		}
	}

	return;
}

// modified from method in includes/class_install
function guess_lang()
{
	global $HTTP_SERVER_VARS, $lang;

	$ret = '';
	// The order here _is_ important, at least for major_minor
	// matches. Don't go moving these around without checking with
	// me first - psoTFX
	$match_lang = array(
		'arabic'					=> 'ar([_-][a-z]+)?',
		'bulgarian'					=> 'bg',
		'catalan'					=> 'ca',
		'czech'						=> 'cs',
		'danish'					=> 'da',
		'german'					=> 'de([_-][a-z]+)?',
		'english'					=> 'en([_-][a-z]+)?',
		'estonian'					=> 'et',
		'finnish'					=> 'fi',
		'french'					=> 'fr([_-][a-z]+)?',
		'greek'						=> 'el',
		'spanish_argentina'			=> 'es[_-]ar',
		'spanish'					=> 'es([_-][a-z]+)?',
		'gaelic'					=> 'gd',
		'galego'					=> 'gl',
		'gujarati'					=> 'gu',
		'hebrew'					=> 'he',
		'hindi'						=> 'hi',
		'croatian'					=> 'hr',
		'hungarian'					=> 'hu',
		'icelandic'					=> 'is',
		'indonesian'				=> 'id([_-][a-z]+)?',
		'italian'					=> 'it([_-][a-z]+)?',
		'japanese'					=> 'ja([_-][a-z]+)?',
		'korean'					=> 'ko([_-][a-z]+)?',
		'latvian'					=> 'lv',
		'lithuanian'				=> 'lt',
		'macedonian'				=> 'mk',
		'dutch'						=> 'nl([_-][a-z]+)?',
		'norwegian'					=> 'no',
		'punjabi'					=> 'pa',
		'polish'					=> 'pl',
		'portuguese_brazil'			=> 'pt[_-]br',
		'portuguese'				=> 'pt([_-][a-z]+)?',
		'romanian'					=> 'ro([_-][a-z]+)?',
		'russian'					=> 'ru([_-][a-z]+)?',
		'slovenian'					=> 'sl([_-][a-z]+)?',
		'albanian'					=> 'sq',
		'serbian'					=> 'sr([_-][a-z]+)?',
		'slovak'					=> 'sv([_-][a-z]+)?',
		'swedish'					=> 'sv([_-][a-z]+)?',
		'thai'						=> 'th([_-][a-z]+)?',
		'turkish'					=> 'tr([_-][a-z]+)?',
		'ukranian'					=> 'uk([_-][a-z]+)?',
		'urdu'						=> 'ur',
		'viatnamese'				=> 'vi',
		'chinese_traditional_taiwan'=> 'zh[_-]tw',
		'chinese_simplified'		=> 'zh',
	);
	$lang_file = 'lang_CH_install';
	$lang_file = $this->root . 'language/lang_%s/' . $lang_file . '.' . $this->ext;

	$file = sprintf($lang_file, 'english');
	if ( @file_exists(@phpbb_realpath($file)) )
	{
		$ret = 'english';
	}
	if ( isset($HTTP_SERVER_VARS['HTTP_ACCEPT_LANGUAGE']) )
	{
		$accepted_langs = explode(',', $HTTP_SERVER_VARS['HTTP_ACCEPT_LANGUAGE']);
		$count_accepted_langs = count($accepted_langs);
		for ( $i = 0; $i < $count_accepted_langs; $i++ )
		{
			foreach ( $match_lang as $lang_available => $match )
			{
				if ( ($lang_available != 'english') && preg_match('#' . $match . '#i', trim($accepted_langs[$i])) )
				{
					$file = sprintf($lang_file, trim($lang_available));
					if ( @file_exists(@phpbb_realpath($file)) )
					{
						$ret = $lang_available;
						return $ret;
					}
				}
			}
		}
	}

	return $ret;
}


function welcome_form()
{
	global $page, $part_script;

?><form name="post" method="post" action="<?php echo $page->url(); ?>"><br /><br /><div align="center"><table cellpadding="4" cellspacing="1" border="0" width="80%" class="background">
<tr><th><?php echo sprintf($page->lang('IN_welcome')); ?></th></tr>
<tr><td align="justify" class="row1"><?php echo sprintf($page->lang('IN_welcome_explain'), $part_script); ?><br /><br /><br /></td></tr>
<tr><td align="center" class="row2"><?php echo $page->lang('IN_start'); ?>: <input name="submit" type="submit" value="<?php echo $page->lang('IN_proceed'); ?>" /></td></tr>
</table></div><?php $page->hide(); ?></form>
<?php
}

function percent_box($title, $percent)
{
	global $page;
	$mult = 2;
	$page->output('<table cellpadding="1" cellspacing="0" border="0"><tr><td>' . $title . ':&nbsp;</td><td style="width: ' . (100 * $mult) . 'px; height: 13px; background-color: #FEFEFF; border: 1px #98AAB1 solid;"><div style="width: ' . ($percent * $mult). 'px; height: 13px; background-color: #00D000;"></div></td></tr></table>');
}

function step()
{
	global $parms, $steps;
	return $steps[ $parms['step'] ];
}

function next_step($step='')
{
	global $page, $parms, $steps;
	if ( !empty($step) )
	{
		$t_steps = array_flip($steps);
		$parms['step'] = $t_steps[$step];
	}
	else
	{
		$parms['step']++;
	}
	$page->set_parms($parms);
}

function get_var($value, $table=CONFIG_TABLE, $key='config_name', $key_value='config_value')
{
	global $db;
	$res = false;

	$sql = 'SELECT ' . $key_value . '
				FROM ' . $table . '
				WHERE ' . $key . '= \'' . $value . '\'';
	$result = $db->sql_query($sql, false, __LINE__, __FILE__);
	if ( $row = $db->sql_fetchrow($result) )
	{
		$res = $row[$key_value];
	}
	$db->sql_freeresult($result);

	return $res;
}

function del_var($value, $table=CONFIG_TABLE, $key='config_name')
{
	global $db;
	$sql = 'DELETE FROM ' . $table . '
			WHERE ' . $key . ' = \'' . $value . '\'';

	return $db->sql_query($sql, false, __LINE__, __FILE__);

}

// load all available includes
$here = dirname(__FILE__);
$pattern = "inc_[a-zA-Z]+";
$fh = opendir($here);
while (($path = readdir($fh)) !== false)
{
	if (ereg($pattern, $path))
	{
		include($here . '/' . $path);
	}
}
@closedir($here);
unset($fh, $here);

// load all install plugs
foreach ($parts as $part)
{
	$$part = new $part();
}

// parms reading
$parms = array();
foreach ( $parms_def as $parm => $data )
{
	$type = empty($data) || !isset($data['type']) ? TYPE_INT : $data['type'];
	$default = empty($data) || !isset($data['default']) ? (($type == TYPE_INT) ? 0 : '') : $data['default'];
	$list = empty($data) || !isset($data['list']) ? '' : $data['list'];
	$parms[$parm] = _read($parm, $type, $default, $list);
}

// start
$page = new page($requester, '', 'lang_CH_installer');
$page->set_parms($parms);

// log in
$session = new light_session();
$session->log_in(ADMIN);

// send welcome
if ( step() == 'IN_welcome' )
{
	$page->header();
	foreach ($parts as $part)
	{
		if ( method_exists($$part, 'start') )
		{
			$$part->start();
		}
	}
	$part_script = implode('<br />', $part_script);
	next_step();
	welcome_form();
	$page->footer();
}

// previous versions
if ( step() == 'IN_prev_vers' )
{
	foreach ($parts as $part)
	{
		if ( method_exists($$part, 'prev_vers') )
		{
			$$part->prev_vers();
		}
	}
	next_step();
	$page->loop($parms);
}

// database
if ( step() == 'IN_db' )
{
	// get the db install layer
	if ( !($sql_layer = $db->get_layer()) )
	{
		$page->critical_error('IN_db_not_supported');
	}
	if ( $sql_layer['SCHEMA'] == 'postgres' )
	{
		$sql_layer['SCHEMA'] = 'pgsql';
	}
	$dbi_layer = 'dbi_' . $sql_layer['SCHEMA'];

	// include the layers
	include($config->url('includes/class_xml'));
	include($config->url('includes/db/class_dbi'));
	include($config->url('includes/db/class_' . $dbi_layer));

	// read the sql instructions
	$schemas = array();
	foreach ($parts as $part)
	{
		if ( method_exists($$part, 'db') )
		{
			$$part->db();
		}
	}
	// process the schemas
	$xml_parser = new xml_parser();
	$dbi = new $dbi_layer($table_prefix);
	$count_schemas = count($schemas);
	for ( $i = 0; $i < $count_schemas; $i++ )
	{
		// read & parse the XML schema
		$actions = false;
		if ( ($xml_name = phpbb_realpath($phpbb_root_path . 'install/schemas/' . $schemas[$i] . '.xml')) && ($handler = @fopen($xml_name, 'r')) )
		{
			$xml = trim(fread($handler, filesize($xml_name)));
			fclose($handler);
			unset($handler);
			$actions = empty($xml) ? false : $xml_parser->parse($xml);
			unset($xml);
			if ( $actions === false )
			{
				$page->critical_error($xml_parser->errmsg);
			}
		}

		// process the sqls
		if ( $actions && isset($actions['cdata']) && ($count_actions = count($actions['cdata'])) )
		{
			for ( $j = 0; $j < $count_actions; $j++ )
			{
				$sqls = isset($actions['cdata'][$j]['actions']) ? $dbi->process($actions['cdata'][$j]['actions']) : false;
				unset($actions['cdata'][$j]);

				$count_sqls = $sqls ? count($sqls) : 0;
				for ( $k = 0; $k < $count_sqls; $k++ )
				{
					$result = $db->sql_query($sqls[$k], false, __LINE__, __FILE__, false);
					if ( $result === false )
					{
						$sql_error = $db->sql_error();
						$page->error(sprintf($page->lang('IN_sql_already_done'), ($sql_error['message'] ? $sql_error['message'] . ': ' : '') . $sqls[$k]));
					}
					else if ( $result !== true )
					{
						$db->sql_freeresult($result);
					}
					unset($result);
				}
				unset($sqls);
			}
		}
		unset($actions);
	}
	unset($dbi);
	unset($xml_parser);
	unset($schemas);
	next_step();
	$page->loop($parms);
}

// upgrade data
if ( step() == 'IN_upgrade' )
{
	foreach ($parts as $part)
	{
		if ( method_exists($$part, 'migrate') )
		{
			$$part->migrate();
		}
	}
	next_step();
	$page->loop($parms);
}

// install fresh data
if ( step() == 'IN_init_data' )
{
	foreach ($parts as $part)
	{
		if ( method_exists($$part, 'init_data') )
		{
			$$part->init_data();
		}
	}
	next_step();
	$page->loop($parms);
}

if ( step() == 'IN_patch' )
{
	foreach ($parts as $part)
	{
		if ( method_exists($$part, 'patch') )
		{
			$$part->patch();
		}
	}

	// instantiate the acting user
	$sav_lang = $lang;
	$user = new user();
	$user->read($session->user_id);

	// patch the panels
	$cp_panels = new cp_panels($requester);
	$cp_panels->read(true);
	$cp_panels->patch(true);

	// remove the acting user
	unset($user);
	$lang = $sav_lang;

	next_step();
}

// all is done, recache
if ( step() == 'IN_end' )
{
	$sql = 'DELETE FROM ' . USERS_CACHE_TABLE;
	$db->sql_query($sql, false, __LINE__, __FILE__);

	foreach ($parts as $part)
	{
		if ( method_exists($$part, 'fin') )
		{
			$$part->fin();
		}
	}
}

// send page
$page->header();
$page->footer();

?>